package com.qianyu.core.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.qianyu.core.api.ApiCommon;
import com.qianyu.core.entity.bean.QqAccount;
import com.qianyu.core.entity.bean.User;
import com.qianyu.core.entity.dto.QqAccountDto;
import com.qianyu.core.entity.dto.api.OpenNotifyDto;
import com.qianyu.core.entity.vo.AppidAndQqVo;
import com.qianyu.core.entity.vo.QqAccountVo;
import com.qianyu.core.enumerate.DataStatusEnum;
import com.qianyu.core.enumerate.ResultEnum;
import com.qianyu.core.exception.CustomerException;
import com.qianyu.core.helper.LoginHelper;
import com.qianyu.core.mapper.QqAccountMapper;
import com.qianyu.core.service.QqAccountService;
import com.qianyu.core.service.UserService;
import com.qianyu.core.util.CacheKeyUtil;
import com.qianyu.core.util.RedisUtil;
import com.qianyu.core.util.TimeUtil;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;

import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Service
@RequiredArgsConstructor
public class QqAccountServiceImpl extends ServiceImpl<QqAccountMapper, QqAccount> implements QqAccountService {

    private final ApiCommon apiCommon;

    private final RedisUtil redisUtil;

    private final UserService userService;

    @Override
    public Page<QqAccount> pageList(QqAccountDto.QqAccountPageDto dto) {
        Page<QqAccount> page = new Page<>(dto.getPageNum(), dto.getPageSize());
        LambdaQueryWrapper<QqAccount> wrapper = Wrappers.lambdaQuery();
        if (!ObjectUtils.isEmpty(dto.getStatus())) {
            wrapper.eq(QqAccount::getStatus, dto.getStatus());
        }
        wrapper.eq(QqAccount::getDeleteStatus, DataStatusEnum.ISABLE.getVal());
        return (Page<QqAccount>) page(page, wrapper);
    }

    @Override
    public Boolean applyAccount(Integer num) {

        String result = apiCommon.applyQq(num);
        JSONObject jsonObject = JSONObject.parseObject(result);
        JSONArray array = jsonObject.getJSONArray("data");
        for (Object o : array) {
            redisUtil.lSet(CacheKeyUtil.applyQqAccountSet(), o);
        }

        return true;
    }

    @Override
    public List<QqAccount> listAccountIsAble(Integer num) {
        LambdaQueryWrapper<QqAccount> wrapper = Wrappers.lambdaQuery();
        wrapper.eq(QqAccount::getStatus, 1)
                .eq(QqAccount::getRentStatus, 0)
                .eq(QqAccount::getDeleteStatus, DataStatusEnum.ISABLE.getVal())
                .orderByAsc(QqAccount::getCreateTime).last(" limit " + num);
        return list(wrapper);
    }

    @Override
    public Page<QqAccountVo.AccountSimpleVo> pageByAgency(QqAccountDto.QqAccountSimplePageDto dto) {
        Page<QqAccount> page = new Page<>(dto.getPageNum(), dto.getPageSize());
        Page<QqAccountVo.AccountSimpleVo> orderPage = new Page<>();
        LambdaQueryWrapper<QqAccount> wrapper = Wrappers.lambdaQuery();
        if (!ObjectUtils.isEmpty(dto.getQq())) {
            wrapper.like(QqAccount::getQq, dto.getQq());
        }
        if (!ObjectUtils.isEmpty(dto.getType())) {
            if (dto.getType() == 0) {
                wrapper.isNull(QqAccount::getUserId);
            } else {
                wrapper.isNotNull(QqAccount::getUserId);
            }
        }
        wrapper.eq(QqAccount::getAgencyId, LoginHelper.getUserId());

        IPage<QqAccount> orderIPage = baseMapper.selectPage(page, wrapper);
        BeanUtil.copyProperties(orderIPage, orderPage);
        orderPage.setRecords(BeanUtil.copyToList(orderIPage.getRecords(), QqAccountVo.AccountSimpleVo.class));
        return orderPage;
    }

    @Override
    public Page<QqAccount> pageByRent(QqAccountDto.QqAccountRentPageDto dto) {
        Map<Long, String> map = userService.list().stream().collect(Collectors.toMap(User::getId, User::getNickname));
        Page<QqAccount> page = new Page<>(dto.getPageNum(), dto.getPageSize());
        LambdaQueryWrapper<QqAccount> wrapper = Wrappers.lambdaQuery();
        if (!ObjectUtils.isEmpty(dto.getStartTime())) {
            wrapper.ge(QqAccount::getDispatchTime, TimeUtil.unixTime(dto.getStartTime()));
        }
        if (!ObjectUtils.isEmpty(dto.getEndTime())) {
            wrapper.le(QqAccount::getDispatchTime, TimeUtil.unixTime(TimeUtil.toDayLastTime(dto.getEndTime())));
        }
        if (dto.getRecoveryStatus() != null) {
            wrapper.eq(QqAccount::getRecoveryStatus, dto.getRecoveryStatus());
        }
        wrapper.eq(QqAccount::getUserId, LoginHelper.getUserId());

        IPage<QqAccount> qqAccountIPage = page(page, wrapper);
        qqAccountIPage.getRecords().forEach(o -> {
            o.setAgencyName(map.get(o.getAgencyId()));
            o.setNickname(map.get(o.getUserId()));
        });
        return (Page<QqAccount>) qqAccountIPage;
    }

    /**
     * 导出登录值
     */
    @Override
    public List<QqAccount> exportAccount() {
        Map<Long, String> map = userService.list().stream().collect(Collectors.toMap(User::getId, User::getNickname));
        LambdaQueryWrapper<QqAccount> wrapper = Wrappers.lambdaQuery();
        wrapper.eq(QqAccount::getUserId, LoginHelper.getUserId());
        List<QqAccount> list = list(wrapper);
        list.forEach(o -> {
            o.setAgencyName(map.get(o.getAgencyId()));
            o.setNickname(map.get(o.getUserId()));
        });
        return list;
    }

    @Override
    public Boolean distributeAccount(QqAccountDto.QqAccountDistributeDto dto) {
        if (CollectionUtils.isEmpty(dto.getAccountIds())) {
            throw new CustomerException(ResultEnum.USER_REQUEST_PARAMETER_ERROR);
        }
        //循环分配账号
        LambdaUpdateWrapper<QqAccount> wrapper = Wrappers.lambdaUpdate();
        wrapper.set(QqAccount::getUserId, dto.getUserId()).set(QqAccount::getDispatchTime, TimeUtil.unixTime())
                .in(QqAccount::getId, dto.getAccountIds())
                .ge(QqAccount::getRentExpire, TimeUtil.unixTime());
        return update(wrapper);
    }

    @Override
    public String getQqOpen(String appid, String loginVal) {
        List<QqAccount> list = list();
        List<QqAccount> accounts = list.stream().filter(q -> q.getLoginVal().equals(loginVal)).collect(Collectors.toList());
        if (CollectionUtil.isNotEmpty(accounts)) {
            QqAccount account = accounts.get(0);
            if (redisUtil.hasKey(CacheKeyUtil.appidAndQqCache(appid, account.getQq()))) {
                return (String) redisUtil.get(CacheKeyUtil.appidAndQqCache(appid, account.getQq()));
            } else {
                AppidAndQqVo vo = new AppidAndQqVo(appid, account.getQq());
                redisUtil.lSet(CacheKeyUtil.getOpenInfoSet(), vo);
            }

        }
        return null;
    }

    @Override
    public AppidAndQqVo getOpen() {
        return (AppidAndQqVo) redisUtil.rGet(CacheKeyUtil.getOpenInfoSet());
    }

    @Override
    public void openNotify(OpenNotifyDto dto) {
        if (dto.getStatus() == 1) {
            redisUtil.set(CacheKeyUtil.appidAndQqCache(dto.getAppid(), dto.getQq()), dto.getOpen(), 600);
        }
    }
}
